EEPROM

reads, writes, and erases a 256-byte serial EEPROM.

One of the best features of the BASIC Stamp hardware is the 93LC56 serial EEPROM. The Stamp uses this device for program space, lookup tables, and nonvolatile data storage.

The program listing presents a series of subroutines that read, write, erase, write-protect, and write-enable the 93LC56. These routines are not port- and pin-independent. The program is based on the circuit shown in the illustration. If you need to change this circuit, make sure to change both the equates for D, CLK and CS, and the data-direction settings for the EEPROM port (mov !ra,x). These are at the start of the program, and in the subroutines EEread and Busy.

The program, which originally appeared in Parallax PIC Application Note #11, writes a rotating bit pattern to the EEPROM, then plays it back on a bank of eight LEDs connected to port RB. Not very exciting, but it verifies every storage cell of the EEPROM with a minimum of programming. Not all programs require the entire set of subroutines. Some are included just for the sake of demonstrating all the EEPROM's capabilities. For example, most programs can do without the routine that erases individual bytes, since a write accomplishes the same thing. And very few programs need to completely erase the EEPROM, or write a single value to all cells. So you should be able to remove EErase, EEwipe, and EEwrall to conserve program-memory space.

For more information on the EEPROM's characteristics and capabilities, please see the current edition of the Microchip Embedded Control Handbook.

Demonstrating EEPROM.

To see EEPROM in operation, connect the circuit below to an erasable PIC or PIC emulator, such as the Parallax downloader. Assemble and run EEPROM.SRC. When you apply power to the PIC, it will write a scanning pattern to the bits of the EEPROM, then read this pattern back onto the LEDs.


;
; ***************************************************************************
; ***  Bubble Software Parallax to PIC Source Converter. Copyright 1999.  ***
; ***  http://www.bubblesoftonline.com                 email: sales@picnpoke.com  ***
; ***************************************************************************
;
; EEPROM (related subroutines)
; This is a collection of subroutines for reading, writing, and
; erasing the 93LC56 (or 'C56) serial EEPROM. As a demonstration, it 
; writes a scanning pattern to the 256 bytes of the EEPROM, and then
; reads it back to eight LEDs connected to port rb. 

	P = pic16c54
	#include <16c54.inc>   ; processor assembler definitions
	_CONFIG _xt_osc & _wdt_off & _protect_off
        reset   start

D            equ        ra.0     ; Pins DI and DO of the EEPROM
CLK          equ        ra.1     ; Clock pin--data valid on rising edge
CS           equ        ra.2     ; Chip select--high = active
ROP          equ       d'192'    ; Opcode for read
WROP         equ       d'160'    ; Opcode for write
EWEN         equ       d'152'    ; Opcode to enable erase and write
EWDS         equ       d'128'    ; Opcode to disable erase and write
ERAS         equ       d'224'    ; Opcode to erase a byte
ERAL         equ       d'144'    ; Opcode to erase all bytes
WRAL         equ       d'136'    ; Opcode to write all bytes

             org     8
temp         Res      d'1'       ; Temporary variable for EE routines
EEdata       Res      d'1'       ; Data to EEwrite/wrall, from EEread
EEaddr       Res      d'1'       ; Address to EErase, EEwrite, EEread
clocks       Res      d'1'       ; Number of clock cycles for SHiftOUT
tick1        Res      d'1'       ; Timer for demo. 
tick2        Res      d'1'       ; Timer for demo. 

             org     0
start        MOVLW d'0'                 ; Clear ports
             MOVWF 5h
             MOVLW d'0'                 
             MOVWF 6h
             MOVLW d'0'                 ; Make all ra pins outputs initially. 
             TRIS 5h
             MOVLW d'0'                 ; Output for LEDs. 
             TRIS 6h
             CALL EEnable               ; Turn off write/erase protection. 
             MOVLW d'1'                 ; EEdata = 1. 
             MOVWF EEdata
             MOVLW d'0'                 ; Start at address 0. 
             MOVWF EEaddr
start_loop   CALL EEwrite               ; Write pattern to EEPROM
             CALL Busy                  ; Wait until done writing. 
             RRF EEdata                 ; Rotate the pattern right. 
             INCFSZ EEaddr              ; FOR EEaddr = 0 to 255...
             GOTO start_loop
             CALL EEdisbl               ; Turn write/erase protection back on. 
start_loop2  CALL EEread                ; Now read back contents of EEPROM. 
             MOVF EEdata,w              ; Display the EEPROM data on LEDs. 
             MOVWF 6h
             INCF EEaddr                ; Set up for next address. 
             CALL delay                 ; Delay to slow down the scanning. 
             GOTO start_loop2           ; Do forever. 

; Shout shifts out the bits of the variable temp to the EEPROM data line. 
; All of the other EEPROM routines call Shout. 
Shout        RLF temp                   ; Rotate bit7 of temp into carry
             BTFSS status,c             ; Move carry bit to input of EEPROM
             BCF 5h,d'0'
             BTFSC status,c
             BSF 5h,d'0'
             BSF 5h,d'1'                ; Clock the bit into EEPROM
             NOP                        ; Clock must be high > 500 ns
             BCF 5h,d'1'                
             DECFSZ clocks              ; FOR I = 1 TO clocks...
             GOTO Shout
             RETLW 0h                   

; Read the byte in EEaddr into EEdata. 
EEread       MOVLW ROP                  ; Move the read opcode into temp        
             MOVWF temp
             MOVLW d'4'                 ; Number of bits to shift out (op+1)
             MOVWF clocks
             BSF 5h,d'2'                ; Select the EEPROM. 
             CALL Shout                 ; Shift the read opcode out. 
             MOVLW d'8'                 ; Number of bits to output (8 addr bits).
             MOVWF clocks
             MOVF EEaddr,w              ; Set up to send the address. 
             MOVWF temp
             CALL Shout                 ; Shift out the address. 
             MOVLW d'1'                 ; Now, change D to input. 
             TRIS 5h
             MOVLW d'8'                 ; Number of bits to input (8 data bits).
             MOVWF clocks
EEread_read  BSF 5h,d'1'                ; Data valid on rising edge of clock. 
             BTFSS 5h,d'0'              ; Data bit into carry. 
             BCF status,c
             BTFSC 5h,d'0'
             BSF status,c
             RLF temp                   ; Rotate carry into temp. 
             BCF 5h,d'1'                ; Falling edge of clock. 
             DECFSZ clocks              ; FOR I = 1 TO 8...
             GOTO EEread_read
             MOVF temp,w                ; Move temp into EEdata
             MOVWF EEdata
             MOVLW d'0'                 ; Restore D to output. 
             TRIS 5h
             BCF 5h,d'2'                ; Deselect the EEPROM. 
             RETLW 0h                   

; Call to unprotect after EEdisbl or power up or any time EEPROM
; has been write protected. 
EEnable      BSF 5h,d'2'                ; Select the EEPROM. 
             MOVLW d'12'                ; Set up to shift out opcode. 
             MOVWF clocks
             MOVLW EWEN                 ; temp = erase/write-enable op code.
             MOVWF temp
             CALL Shout                 ; Shift temp out to the EEPROM. 
             BCF 5h,d'2'                ; Done. Deselect EEPROM. 
             RETLW 0h                   

; Call to protect against accidental write/erasure. Manufacturer advises
; leaving EEPROM in write-protected state most of the time to prevent accidental
; alteration by a runaway program. 
EEdisbl      BSF 5h,d'2'                ; Select the EEPROM. 
             MOVLW d'12'                ; Set up to shift out opcode. 
             MOVWF clocks
             MOVLW EWDS                 ; temp = erase/write-disable op code.
             MOVWF temp
             CALL Shout                 ; Shift temp out to the EEPROM. 
             BCF 5h,d'2'                ; Done. Deselect EEPROM. 
             RETLW 0h                   

; Write the byte in EEdata to EEaddr. 
EEwrite      MOVLW WROP                 ; Get the write op code. 
             MOVWF temp
             MOVLW d'4'                 ; Prepare to shift out 4 msbs. 
             MOVWF clocks
             BSF 5h,d'2'                ; Select the EEPROM. 
             CALL Shout                 ; Shift temp out to the EEPROM. 
             MOVLW d'8'                 ; Now prepare for 8 addr bits. 
             MOVWF clocks
             MOVF EEaddr,w              ; Move address into temp. 
             MOVWF temp
             CALL Shout                 ; Shift temp out to the EEPROM. 
             MOVLW d'8'                 ; Prepare for 8 data bits. 
             MOVWF clocks
             MOVF EEdata,w              ; Move data into temp. 
             MOVWF temp
             CALL Shout                 ; Shift temp out to the EEPROM. 
             BCF 5h,d'2'                ; Done. Deselect EEPROM. 
             RETLW 0h                   

; Erase the byte in EEaddr. Erasure leaves 0FFh (all 1s) in the byte.
EErase       MOVLW ERAS                 ; Get the erase op code. 
             MOVWF temp
             MOVLW d'4'                 ; Prepare to shift out 4 msbs. 
             MOVWF clocks
             BSF 5h,d'2'                ; Select the EEPROM. 
             CALL Shout                 ; Shift temp out to the EEPROM. 
             MOVLW d'8'                 ; Prepare for 8 addr bits. 
             MOVWF clocks
             MOVF EEaddr,w              ; Move address into temp. 
             MOVWF temp
             CALL Shout                 ; Shift address out to the EEPROM. 
             BCF 5h,d'2'                ; Done. Deselect EEPROM. 
             RETLW 0h                   

; Erase the entire EEPROM--all 256 bytes. Call before using EEwrall below. 
EEwipe       BSF 5h,d'2'                ; Select the EEPROM. 
             MOVLW ERAL                 ; Get the erase-all opcode. 
             MOVWF temp
             MOVLW d'12'                ; Prepare to shift out 12 bits. 
             MOVWF clocks
             CALL Shout                 ; Send op code + don't-care bits.
             BCF 5h,d'2'                ; Done. Deselect EEPROM. 
             RETLW 0h                   

; Write the byte in EEdata to every address. Call EEwipe first.
EEwrall      BSF 5h,d'2'                ; Select the EEPROM. 
             MOVLW WRAL                 ; Get the write-all opcode. 
             MOVWF temp
             MOVLW d'12'                ; Prepare to shift out 12 bits. 
             MOVWF clocks
             CALL Shout                 ; Send op code + don't-care bits.
             MOVLW d'8'                 ; Prepare to shift out 8 data bits. 
             MOVWF clocks
             MOVF EEdata,w              ; Move data into temp. 
             MOVWF temp
             CALL Shout                 ; Shift temp out to EEPROM. 
             BCF 5h,d'2'                ; Done. Deselect EEPROM. 
             RETLW 0h                   

; Check flag to determine whether the EEPROM has finished its self-timed
; erase/write. Caution: This will lock up your program until D goes high. 
Busy         MOVLW d'1'                 ; Set D to input. 
             TRIS 5h
             BSF 5h,d'2'                ; Select the EEPROM. 
Busy_wait    BTFSS 5h,d'0'              ; Wait until D goes high (end of write). 
             GOTO Busy_wait
             BCF 5h,d'2'                ; Done. Deselect EEPROM. 
             MOVLW d'0'                 ; Restore D to output. 
             TRIS 5h
             RETLW 0h                   

; Delay routine for demo. 
Delay        DECFSZ tick1               
             GOTO Delay
             DECFSZ tick2               
             GOTO Delay
             RETLW 0h                   



; EEPROM (related subroutines)
; This is a collection of subroutines for reading, writing, and
; erasing the 93LC56 (or 'C56) serial EEPROM. As a demonstration, it 
; writes a scanning pattern to the 256 bytes of the EEPROM, and then
; reads it back to eight LEDs connected to port rb. 

        device  pic16c54,xt_osc,wdt_off,protect_off
        reset   start

D       =       ra.0    ; Pins DI and DO of the EEPROM
CLK     =       ra.1    ; Clock pin--data valid on rising edge
CS      =       ra.2    ; Chip select--high = active
ROP     =       192     ; Opcode for read
WROP    =       160     ; Opcode for write
EWEN    =       152     ; Opcode to enable erase and write
EWDS    =       128     ; Opcode to disable erase and write
ERAS    =       224     ; Opcode to erase a byte
ERAL    =       144     ; Opcode to erase all bytes
WRAL    =       136     ; Opcode to write all bytes

        org     8
temp    ds      1       ; Temporary variable for EE routines
EEdata  ds      1       ; Data to EEwrite/wrall, from EEread
EEaddr  ds      1       ; Address to EErase, EEwrite, EEread
clocks  ds      1       ; Number of clock cycles for SHiftOUT
tick1   ds      1       ; Timer for demo. 
tick2   ds      1       ; Timer for demo. 

        org     0
start   mov     ra,#0           ; Clear ports
        mov     rb,#0   
        mov     !ra,#0          ; Make all ra pins outputs initially. 
        mov     !rb,#0          ; Output for LEDs. 
        call    EEnable         ; Turn off write/erase protection. 
        mov     EEdata,#1       ; EEdata = 1. 
        mov     EEaddr,#0       ; Start at address 0. 
:loop   call    EEwrite         ; Write pattern to EEPROM
        call    Busy            ; Wait until done writing. 
        rr      EEdata          ; Rotate the pattern right. 
        ijnz    EEaddr,:loop    ; FOR EEaddr = 0 to 255...
        call    EEdisbl         ; Turn write/erase protection back on. 
:loop2  call    EEread          ; Now read back contents of EEPROM. 
        mov     rb,EEdata       ; Display the EEPROM data on LEDs. 
        inc     EEaddr          ; Set up for next address. 
        call    delay           ; Delay to slow down the scanning. 
        goto    :loop2          ; Do forever. 

; Shout shifts out the bits of the variable temp to the EEPROM data line. 
; All of the other EEPROM routines call Shout. 
Shout   rl      temp            ; Rotate bit7 of temp into carry
        movb    D,c             ; Move carry bit to input of EEPROM
        setb    CLK             ; Clock the bit into EEPROM
        nop                     ; Clock must be high > 500 ns
        clrb    CLK
        djnz    clocks,Shout    ; FOR I = 1 TO clocks...
        ret

; Read the byte in EEaddr into EEdata. 
EEread  mov     temp,#ROP       ; Move the read opcode into temp        
        mov     clocks,#4       ; Number of bits to shift out (op+1)
        setb    CS              ; Select the EEPROM. 
        call    Shout           ; Shift the read opcode out. 
        mov     clocks,#8       ; Number of bits to output (8 addr bits).
        mov     temp,EEaddr     ; Set up to send the address. 
        call    Shout           ; Shift out the address. 
        mov     !ra,#1          ; Now, change D to input. 
        mov     clocks,#8       ; Number of bits to input (8 data bits).
:read   setb    CLK             ; Data valid on rising edge of clock. 
        movb    c,D             ; Data bit into carry. 
        rl      temp            ; Rotate carry into temp. 
        clrb    CLK             ; Falling edge of clock. 
        djnz    clocks,:read    ; FOR I = 1 TO 8...
        mov     EEdata,temp     ; Move temp into EEdata
        mov     !ra,#0          ; Restore D to output. 
        clrb    CS              ; Deselect the EEPROM. 
        ret

; Call to unprotect after EEdisbl or power up or any time EEPROM
; has been write protected. 
EEnable setb    CS              ; Select the EEPROM. 
        mov     clocks,#12      ; Set up to shift out opcode. 
        mov     temp,#EWEN      ; temp = erase/write-enable op code.
        call    Shout           ; Shift temp out to the EEPROM. 
        clrb    CS              ; Done. Deselect EEPROM. 
        ret

; Call to protect against accidental write/erasure. Manufacturer advises
; leaving EEPROM in write-protected state most of the time to prevent accidental
; alteration by a runaway program. 
EEdisbl setb    CS              ; Select the EEPROM. 
        mov     clocks,#12      ; Set up to shift out opcode. 
        mov     temp,#EWDS      ; temp = erase/write-disable op code.
        call    Shout           ; Shift temp out to the EEPROM. 
        clrb    CS              ; Done. Deselect EEPROM. 
        ret

; Write the byte in EEdata to EEaddr. 
EEwrite mov     temp,#WROP      ; Get the write op code. 
        mov     clocks,#4       ; Prepare to shift out 4 msbs. 
        setb    CS              ; Select the EEPROM. 
        call    Shout           ; Shift temp out to the EEPROM. 
        mov     clocks,#8       ; Now prepare for 8 addr bits. 
        mov     temp,EEaddr     ; Move address into temp. 
        call    Shout           ; Shift temp out to the EEPROM. 
        mov     clocks,#8       ; Prepare for 8 data bits. 
        mov     temp,EEdata     ; Move data into temp. 
        call    Shout           ; Shift temp out to the EEPROM. 
        clrb    CS              ; Done. Deselect EEPROM. 
        ret

; Erase the byte in EEaddr. Erasure leaves 0FFh (all 1s) in the byte.
EErase  mov     temp,#ERAS      ; Get the erase op code. 
        mov     clocks,#4       ; Prepare to shift out 4 msbs. 
        setb    CS              ; Select the EEPROM. 
        call    Shout           ; Shift temp out to the EEPROM. 
        mov     clocks,#8       ; Prepare for 8 addr bits. 
        mov     temp,EEaddr     ; Move address into temp. 
        call    Shout           ; Shift address out to the EEPROM. 
        clrb    CS              ; Done. Deselect EEPROM. 
        ret

; Erase the entire EEPROM--all 256 bytes. Call before using EEwrall below. 
EEwipe  setb    CS              ; Select the EEPROM. 
        mov     temp,#ERAL      ; Get the erase-all opcode. 
        mov     clocks,#12      ; Prepare to shift out 12 bits. 
        call    Shout           ; Send op code + don't-care bits.
        clrb    CS              ; Done. Deselect EEPROM. 
        ret

; Write the byte in EEdata to every address. Call EEwipe first.
EEwrall setb    CS              ; Select the EEPROM. 
        mov     temp,#WRAL      ; Get the write-all opcode. 
        mov     clocks,#12      ; Prepare to shift out 12 bits. 
        call    Shout           ; Send op code + don't-care bits.
        mov     clocks,#8       ; Prepare to shift out 8 data bits. 
        mov     temp,EEdata     ; Move data into temp. 
        call    Shout           ; Shift temp out to EEPROM. 
        clrb    CS              ; Done. Deselect EEPROM. 
        ret

; Check flag to determine whether the EEPROM has finished its self-timed
; erase/write. Caution: This will lock up your program until D goes high. 
Busy    mov     !ra,#1          ; Set D to input. 
        setb    CS              ; Select the EEPROM. 
:wait   jnb     D,:wait         ; Wait until D goes high (end of write). 
        clrb    CS              ; Done. Deselect EEPROM. 
        mov     !ra,#0          ; Restore D to output. 
        ret

; Delay routine for demo. 
Delay   djnz    tick1,Delay     
        djnz    tick2,Delay
        ret

See also:

Questions: